/*!
 * DOMAssistant Selection 0.9, Copyright (c) 2008 Pelle Wessman, <http://code.google.com/p/domeffects>, MIT Style License.
 */
/**
 * @fileOverview Basic support for cross browser work with selections within DOMAssistant
 * @name DOMAssistant Selection
 */

//TODO Make window and document relative to the element

/*extern DOMAssistant, $ */

/** @scope DOMAssistant */
DOMAssistant.attach({
	/**
	 * Checks whether an element is a child of the current element - or if it is the current element
	 * @param  {object}  elem The DOM-node to search for
	 * @return {boolean} True if the element is a child or the current element
	 * @example $('div').first().haveChild($$('cool')); //Returns true if the element with the id "cool" is a child of the first div on the page
	 */
	haveChild : function (elem) {
		do {
			if (elem === this) {
				return true;
			}
			elem = elem.parentNode;
		} while (elem);
		return false;
	},

	/**
	 * Returns the selection contained inside the current element
	 * @return {string} The content of the selection - an empty string if nothing is selected
	 * @example $('div').first().getSelect(); //Returns the content of the selection contained within the first div of the page
	 */
	getSelect : function () {
		var content = '', range;
		if (window.getSelection && window.getSelection().rangeCount) {
			range = window.getSelection().getRangeAt(0);
			if ($(this).haveChild(range.commonAncestorContainer)) {
				content = range.toString();
			}
		} else if (document.selection) {
	        range = document.selection.createRange();
			if ($(this).haveChild(range.parentElement())) {
				content = range.text;
			}
	    } else if (this.selectionStart !== undefined) {
	        var startPos = this.selectionStart,
	        endPos = this.selectionEnd;
	        content = this.value.substring(startPos, endPos);
	    }
		return content;
	},

	/**
	 * Replaces the content of a selection with new data - if no selection is contained within the element it does nothing
	 * @param  {string}  content The content to replace the selection with
	 * @param  {boolean} [html]  Whether the string should be inserted as HTML or not
	 * @return {object} The element itself to enable chaining
	 * @example $('div').first().setSelect('Apples are nice'); //Sets the content of the selection contained in the first div on the page to 'Apples are nice'
	 */
	setSelect : function (content, html) {
		var range;
		if (window.getSelection && window.getSelection().rangeCount) {
			range = window.getSelection().getRangeAt(0);
			if ($(this).haveChild(range.commonAncestorContainer)) {
				range.deleteContents();
				var elem;
				if (html) {
					var span = document.createElement('span');
					span.innerHTML = content;
					elem = document.createDocumentFragment();
					for (var i = 0, length = span.childNodes.length; i < length; i++) {
						elem.appendChild(span.childNodes[i]);
					}
					span = null;
				} else {
					elem = document.createTextNode(content)
				}
				range.insertNode(elem);
			}
	    } else if (document.selection) {
	        range = document.selection.createRange();
			if ($(this).haveChild(range.parentElement())) {
				if (html) {
					range.pasteHTML(content);
				} else {
					range.text = content;
				}
			}
	    } else if (this.selectionStart !== undefined) {
			//TODO: HTML???
	        var startPos = this.selectionStart,
	        endPos = this.selectionEnd,
	        beforeText = this.value.substring(0, startPos),
	        afterText = this.value.substring(endPos, this.value.length);
	        this.value = beforeText + content + afterText;
	    }
		return this;
	},

	/**
	 * Adds text to the end of the selection and if given also adds text to the beginning of the selection
	 * @param  {string}  after    The content to add to the end of the selection
	 * @param  {string}  [before] The content to add to the beginning of the selection
	 * @param  {boolean} [html]   Whether the string should be inserted as HTML or not
	 * @return {object} The element itself to enable chaining
	 * @example $('div').first().wrapSelect('Apples are ', ' therefor we like them'); //If the selected text in the first div are "red and delicious" then it will be "Apples are red and delicious and therefor we like them" after this function-call
	 */
	wrapSelect : function (after, before, html) {
		if (typeof before !== 'string') {
			before = '';
		}
		var selection = $(this).getSelect();
		$(this).setSelect(before + selection + after, html);
	    return this;
	}
});